#include "HLS.h"
namespace Media
{
	HLS::HLS(
		const HLSParam &hls_param,
		AVCodecContext* in_video_codec, 
		AVCodecContext* in_audio_codec):m_hls_param(hls_param), StreamMuxingBase(ENUM_STREAM_MPEGTS,
			in_video_codec, in_audio_codec)
	{
		
	}

	bool HLS::streamOut2Memory(uint8_t* buf, int buf_size)
	{
		std::shared_ptr<StreamPacket> stream_packet(new StreamPacket(buf, buf_size));
		this->m_stream_packet_list.push_back(stream_packet);
		return true;
	}


	// 塞入数据 true:添加成功 false：失败重试其他
	bool HLS::addPacket(const ENUM_MEDIA_TYPE& type, AVPacket* packet)
	{
		
		switch (type)
		{
			case ENUM_MEDIA_TYPE::VIDEO: {
				av_packet_rescale_ts(packet, p_in_video_codec_centext->time_base, p_out_video_stream->time_base);
				packet->stream_index = m_video_out_index;
				
				// 用I帧来判断这个流是不是该切了
				if (packet->flags & AV_PKT_FLAG_KEY)
				{
					//Log::printInfo("hls find I");
					m_cut_end_pts = packet->pts * av_q2d(p_out_video_stream->time_base) * 1000;

					if (!m_hls_node_cut_start)
					{
						m_cut_start_pts = m_cut_end_pts;
					}

					// 开始切
					m_hls_node_cut_start = true;
					
					double duration = m_cut_end_pts - m_cut_start_pts;
					if (duration >= m_hls_param.getTSTime() && 0 != duration)
					{
						m_cut_start_pts = m_cut_end_pts;
						// 切ts切片
						this->createM3U8AndTS(duration);
					}
				}

				if (m_hls_node_cut_start)
				{
					//std::cout << "送入帧:" << m_songru++ << std::endl;
					/* Write the compressed frame to the media file. */
					//StreamMuxingBase::log_packet(p_out_formatctx, packet, "视频");
					int ret = av_interleaved_write_frame(p_out_formatctx, packet);
					if (ret < 0)
					{
						std::cout << "视频压入HLS包失败" << std::endl;
						return false;
					}
					
				}
				
			}; break;
			case ENUM_MEDIA_TYPE::AUDIO: {
				av_packet_rescale_ts(packet, p_in_audio_codec_centext->time_base, p_out_audio_stream->time_base);
				packet->stream_index = m_audio_out_index;
				// 没切的情况有两种 1.视频刚开始串流  2.切满了
				if (m_hls_node_cut_start)
				{
					//StreamMuxingBase::log_packet(p_out_formatctx, packet, "音频");
					int ret = av_interleaved_write_frame(p_out_formatctx, packet);
					if (ret < 0)
					{
						std::cout << "音频压入HLS包失败" << std::endl;
						return false;
					}
				}
				
			}; break;
			default:
				return false;
				break;
		}
		av_interleaved_write_frame(p_out_formatctx, NULL);
		

		return true;
	}

	int HLS::getTsIndex()
	{
		if (m_ts_index >= m_hls_param.getTSIndexMax())
		{
			m_ts_index = 1;
		}
		m_ts_index++;
		return m_ts_index;
	}

	

	bool HLS::createM3U8AndTS(const double& time)
	{
		m_m3u8_drution_list.push_back(time);
		int ts_index = getTsIndex();
		//size_t len = 0;

		std::shared_ptr<StreamPacket> ts_packet(new StreamPacket());

		// 将所有的切片进行序列化
		for (auto it = m_stream_packet_list.begin();
			it != m_stream_packet_list.end();
			it++)
		{
			auto ts_data = (*it)->getData();
			auto ts_len = (*it)->getLen();
			/*if (len+ ts_len > MAX_TS_BUFFER_SZIE)
			{
				Log::printError("ts长度超限制");
				break;
			}*/
			
			ts_packet.get()->pushData(ts_data, ts_len);
			//std::cout << "单个ts长度" << ts_len << std::endl;
			//memcpy(p_stream_buffer +len, ts_data, ts_len);
			//len += ts_len;
			
		}
		m_stream_packet_list.clear();

		// 挑出一个时长最大的切片
		while (m_m3u8_drution_list.size() > m_hls_param.getTSCount())
		{
			// 如果长度大于ts个数则pop一个直到pop到之声预期个数
			m_m3u8_drution_list.erase(m_m3u8_drution_list.begin());
		}
		auto tmp_sort_drution_list = m_m3u8_drution_list;
		std::sort(tmp_sort_drution_list.begin(), tmp_sort_drution_list.end(), [](const double& a, const double& b) {
			return a > b;
		});
		auto perfect_durtion = tmp_sort_drution_list.front();


		

		std::string index_ts = m_hls_param.getIndex() + "/" + std::to_string(ts_index) + ".ts";

		std::string m3u8_item = "#EXTINF: "+std::to_string(double(time/1000)) + std::string(",\n")  +std::to_string(ts_index) + ".ts\n";
		m_m3u8_last_item_list.push_back(m3u8_item);
		// 点播请把这行注释掉
		while (m_m3u8_last_item_list.size() > m_hls_param.getTSCount())
		{
			m_m3u8_last_item_list.pop_front();
		}

		
		std::string tmp_m3u8 = m_m3u8_head + std::to_string(int(perfect_durtion)/1000) + "\n"
			+ m_m3u8_sequence
			+ std::to_string(m_m3u8_sequence_count++) + "\n";
		for (auto it = m_m3u8_last_item_list.begin();
			it != m_m3u8_last_item_list.end(); 
			it++)
		{
			tmp_m3u8 += (*it);
		}
		
		/*std::cout << "ts时间:" << time << " ts名称:" << ts_index <<
			std::endl<< "m3u8:"<<std::endl<<
			tmp_m3u8 << std::endl;*/

		auto hls_mq = m_hls_param.getMQ();
		if (hls_mq != nullptr)
		{
			std::string hls_m3u8_path =  m_hls_param.getIndex() + "/index.m3u8";
			// 打包协议序列化插入
			HlsSerialize hls_serialize(hls_m3u8_path,tmp_m3u8, index_ts, ts_packet->getData(), ts_packet->getLen());
			hls_mq->pushBack(hls_serialize.getStreamPacket());
		}
	
		return true;
	}


	HLS::~HLS()
	{
		
	}




}
